import json
import os.path
import re
import subprocess

import requests
from PyQt5 import QtCore
from PyQt5.QtCore import QObject
from PyQt5.QtWidgets import QListWidgetItem
from lxml import html

from config import TEMPFOLDER, OUT_FOLDER


def get_value(nums: list, index: int):
    length = len(nums)
    if nums and index < length:
        return nums[index]
    raise None


class DownloadThread(QObject):
    progress_video = QtCore.pyqtSignal(int)
    progress_audio = QtCore.pyqtSignal(int)
    progress_finish = QtCore.pyqtSignal(str)

    def __init__(self, other_obj, parent=None):
        super(DownloadThread, self).__init__(parent)
        self.other_obj = other_obj

    def run(self):
        global title
        try:
            # 获取下载任务
            items = self.other_obj.download_list
            # 获取下载任务的数量
            length = len(items)

            for index in range(length):

                title = get_value(items[index], 0)

                # 删除标题中的无效值
                title = remove_invalid_chars(title)

                print(f"正在下载video: {title}")
                video_url = get_value(items[index], 1)
                audio_url = get_value(items[index], 2)

                video_path = f"{title}.mp4"
                audio_path = f"{title}.mp3"

                # 拼接路径
                video_path = os.path.join(os.getcwd(), TEMPFOLDER, video_path)
                audio_path = os.path.join(os.getcwd(), TEMPFOLDER, audio_path)

                response = requests.get(video_url, headers=self.other_obj.headers, stream=True, timeout=10)
                total_size = int(response.headers.get('content-length', 0))
                with open(video_path, 'wb') as file:
                    chunk_size = 1024
                    for data in response.iter_content(chunk_size=chunk_size):
                        file.write(data)
                        downloaded_size = file.tell()
                        if total_size > 0:
                            progress = int(downloaded_size * 100 / total_size)
                            # 更新视频进度条
                            self.progress_video.emit(progress)

                response = requests.get(audio_url, headers=self.other_obj.headers, stream=True, timeout=10)
                total_size = int(response.headers.get('content-length', 0))
                with open(audio_path, 'wb') as file:
                    chunk_size = 1024
                    for data in response.iter_content(chunk_size=chunk_size):
                        file.write(data)
                        downloaded_size = file.tell()
                        if total_size > 0:
                            progress = int(downloaded_size * 100 / total_size)
                            # 更新音频进度条
                            self.progress_audio.emit(progress)

                # 删除下载列表中的任务
                self.other_obj.download_list.pop(index)

                # 通知主线程当前视频下载完成
                self.progress_finish.emit(title)

        except BaseException as error:
            # 通知主线程当前视频下载完成
            self.progress_finish.emit(title)
            print(error)
            return


class ParseThread(QtCore.QThread):

    def __init__(self, urls, other_obj, parent=None):
        super(ParseThread, self).__init__(parent)
        self.urls = urls
        self.other_obj = other_obj

    def run(self):
        try:

            for url in self.urls:
                # 执行下载任务
                response = requests.get(url, headers=self.other_obj.headers, stream=True)
                obj = re.compile(r'window.__playinfo__=(.*?)</script>', re.S)
                etree = html.etree
                tree = etree.HTML(response.text)

                title = tree.xpath('//*[@id="viewbox_report"]/div[1]/div/h1/text()')

                # 标题解析
                if title:

                    title = get_value(title, 0).strip().replace(' ', '')
                else:
                    self.finished.emit()
                    return

                html_data = obj.findall(response.text)[0]
                json_data = json.loads(html_data)
                videos = json_data['data']['dash']['video']
                video_url = videos[0]['baseUrl']  # 视频地址
                audios = json_data['data']['dash']['audio']
                audio_url = audios[0]['baseUrl']  # 音频地址

                # 显示到界面上
                list_item = QListWidgetItem()
                list_item.setText(title)

                # 添加子控件
                self.other_obj.listWidget.addItem(list_item)
                # 存储到全局中
                self.other_obj.parse_result.append((title, video_url, audio_url))

            # 完成后，发出信号通知主线程
            self.finished.emit()

        except BaseException as error:
            print(error)
            # 完成后，发出信号通知主线程
            self.finished.emit()
            return


class MergeThread(QtCore.QThread):
    progress = QtCore.pyqtSignal(int)

    def __init__(self):
        super(MergeThread, self).__init__()

    def run(self):
        items: list = find_same_name_files(TEMPFOLDER, OUT_FOLDER)
        length = len(items)
        for index, files in enumerate(items):
            video_path = files[0]
            audio_path = files[1]

            # 拼接输出路径
            video_path = os.path.join(os.getcwd(), video_path)
            audio_path = os.path.join(os.getcwd(), audio_path)
            out_file = os.path.split(video_path)[1]
            out_path = os.path.join(os.getcwd(), OUT_FOLDER, out_file)

            # # 使用ffmpeg合并视频和音频
            command = f'ffmpeg -i "{video_path}" -i "{audio_path}" -c:v copy -c:a aac "{out_path}"'
            subprocess.call(command, shell=True)

            # 计算任务百分点
            progress_value = int(((index + 1) / length) * 100)
            # # 在合并完成后，发出信号通知主线程
            self.progress.emit(progress_value)


def find_same_name_files(folder_path, out_folder) -> list:
    mp3_files = {}
    mp4_files = {}
    out_files = {}
    # 遍历文件夹
    for root, dirs, files in os.walk(folder_path):
        for file in files:
            # 如果文件名以.mp3结尾，则记录文件路径
            if file.endswith('.mp3'):
                mp3_files[file.replace('.mp3', '')] = os.path.join(root, file)
            # 如果文件名以.mp4结尾，则记录文件路径
            elif file.endswith('.mp4'):
                mp4_files[file.replace('.mp4', '')] = os.path.join(root, file)

    for root, dirs, files in os.walk(out_folder):
        for file in files:
            # 如果文件名以.mp4结尾，则记录文件路径
            if file.endswith('.mp4'):
                out_files[file.replace('.mp4', '')] = os.path.join(root, file)

    # 找出相同名字的mp3和mp4文件,并且没有合并过的文件
    same_name_files = []
    for key in mp4_files:
        if key in mp3_files and key not in out_files:
            same_name_files.append([mp4_files[key], mp3_files[key]])

    return same_name_files


def remove_invalid_chars(text):
    clean_text = re.sub(r'[^\w\s]', '', text)
    return clean_text
